/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.deployment.figure;

import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.uml2.uml.Element;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;

/**
 * Defines the view of a node.
 * 
 * @author Gilles Cannenterre
 * @since 16 janv. 07
 */
public class BasicNodeCubeFigure extends NodeFigure {

	/**
	 * The Class UseCaseLabelFigure.
	 * Holds the names and stereotypes.
	 */
	protected class NodeLabelFigure extends NodeFigure {
		
		/**
		 * The Constructor.
		 */
		public NodeLabelFigure() {
			super();
			Debug.debug(this, "LabelFigure()", channel);
			ToolbarLayout layout = new ToolbarLayout();
			setLayoutManager(layout);
			layout.setSpacing(2);
		}
	
		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 */
		@Override
		public void setBounds(Rectangle rect) {
	
			int labelHeight = 20;
			int labelWidth  = rect.width - PERSPECTIV_DEPTH - 2;
	
			// Calculate height
			if (getStereotypesLabel() != null) {
				labelHeight = labelHeight + getStereotypesLabel().getPreferredSize().height;
			}
			if (getQualifiedNameLabel() != null) {
				labelHeight = labelHeight + getQualifiedNameLabel().getPreferredSize().height;
			}
			if (getIconLabel() != null) {
				if (getIconLabel().getIcon() != null) {
					labelHeight = labelHeight + getIconLabel().getPreferredSize().height;
				}			
			}
			
			Rectangle labelRect = new Rectangle();
			if (keywordFigure != null) {
				labelRect.setLocation(0, PERSPECTIV_DEPTH + keywordFigure.getSize().height);
			} else {
				labelRect.setLocation(0, PERSPECTIV_DEPTH);
			}
			labelRect.setSize(labelWidth, labelHeight);
			
			super.setBounds(labelRect);
			Debug.debug(this," bounds are : " +getBounds(), channel);
		}
	
		/**
		 * Paint border.
		 * 
		 * @param graphics the graphics
		 */
		@Override
		public void paintBorder(Graphics graphics){
			if (isNameUnderlined) {
				graphics.setForegroundColor(labelFigure.getFontColor());
				Rectangle rectLabel = labelFigure.getBounds();
				Dimension labelSize=FigureUtilities.getTextExtents(labelFigure.getNameLabel().getText(), labelFigure.getNameLabel().getFont());
				graphics.drawLine(rectLabel.x+rectLabel.width/2-labelSize.width/2,
						rectLabel.y+rectLabel.height-2,
						rectLabel.x+rectLabel.width/2+labelSize.width/2,
						rectLabel.y+rectLabel.height-2);
			}
		}
	}

	/**
	 * display the content of the package
	 * *.
	 */
	protected class NodeContentFigure extends NodeFigure  {
	
		/**
		 * 
		 */
		private IFigure pane;
		
		/**
		 * 
		 */
		protected ScrollPane scrollpane;
	
		/**
		 * 
		 */
		public NodeContentFigure() {
			// Set content layout
			setLayoutManager(new StackLayout());
	
			// Add pane for content
			pane = new FreeformLayer();
			pane.setLayoutManager(new FreeformLayout());
	
			// Add scrollpane
			ScrollPane scrollpane = new ScrollPane();
			scrollpane.setViewport(new FreeformViewport());
			scrollpane.setContents(pane);
			add(pane);
		}
	
		/**
		 * 
		 * 
		 * @return 
		 */
		public IFigure getContentPane() {
			return pane;
		}
	
		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 * 
		 * @see setDimension
		 */	
		@Override
		public void setBounds(Rectangle rect) {
			// Father dimension
			int fatherHeight = getParent().getSize().height - PERSPECTIV_DEPTH - 2;
			
			int contentHeight = 0;
			int contentWidth = labelFigure.getSize().width;
			
			Rectangle containerLabelRect = new Rectangle();
			if (keywordFigure != null) {
				contentHeight = fatherHeight - keywordFigure.getSize().height - labelFigure.getSize().height - 1;
				containerLabelRect.setLocation(0, PERSPECTIV_DEPTH +  keywordFigure.getSize().height+ labelFigure.getSize().height);
			} else {
				contentHeight = fatherHeight - labelFigure.getSize().height - 1;
				containerLabelRect.setLocation(0, PERSPECTIV_DEPTH + labelFigure.getSize().height);
			}
			containerLabelRect.setSize(contentWidth, contentHeight);
	
			super.setBounds(containerLabelRect);
		}

		/**
		 * Paint border.
		 * 
		 * @param graphics the graphics
		 */
		@Override
		public void paintBorder(Graphics graphics){	}
	}

	/**
	 * The Class ActorKeywordFigure.
	 * Holds the keyword <<actor>>
	 */
	protected class NodeKeywordFigure extends NodeFigure {
		
		/**
		 * The Constructor.
		 */
		public NodeKeywordFigure() {
			super();
			ToolbarLayout layout = new ToolbarLayout(ToolbarLayout.VERTICAL); 
			layout.setStretchMinorAxis(true);
			layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
			setLayoutManager(layout);
		}
	
		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 */
		@Override
		public void setBounds(Rectangle rect) {
			Debug.debug(this, "setBounds(Rectangle)", channel);
			int keywordHeight = 20;
			int keywordWidth  = rect.width - PERSPECTIV_DEPTH - 2;;
			
			Rectangle keywordRect = new Rectangle();
			keywordRect.setLocation(0, PERSPECTIV_DEPTH);
			keywordRect.setSize(keywordWidth, keywordHeight);
	
			super.setBounds(keywordRect);	
			Debug.debug(this," bounds are : " +getBounds(), channel);
		}
	
		/**
		 * Paint border.
		 * 
		 * @param graphics the graphics
		 */
		@Override
		public void paintBorder(Graphics graphics){	}
	}

	/**
	 * 
	 */
	protected NodeContentFigure contentFigure;

	/**
	 * The label figure.
	 */
	protected NodeLabelFigure labelFigure;

	/**
	 * The channel.
	 */
	private int channel = 204;

	/**
	 * The keyword figure.
	 */
	protected NodeKeywordFigure keywordFigure;

	/**
	 * The is name underlined.
	 */
	protected boolean isNameUnderlined = false;

	/**
	 * 
	 */
	protected static final int PERSPECTIV_DEPTH = 10;

	/**
	 * 
	 * 
	 * @param keyword 
	 */
	public BasicNodeCubeFigure(String keyword)	{
		super();
		setOpaque(true);
		if (keyword != null) { 
			keywordFigure = new NodeKeywordFigure();
			keywordFigure.setName(PapyrusPlugin.ST_LEFT+keyword+PapyrusPlugin.ST_RIGHT);
			add(keywordFigure);
		}
		labelFigure = new NodeLabelFigure();
		add(labelFigure);	
		contentFigure =new NodeContentFigure();
		add(contentFigure);	
	}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public IFigure getContentPane()	{
		return contentFigure.getContentPane();	
	}

	/**
	 * 
	 * 
	 * @param graphics 
	 */
	public void paintFigure(Graphics graphics) {
		//super.paintFigure(graphics);
		Rectangle rect = getBounds().getCopy();		
		graphics.translate(getLocation());

		// fill the cube
		PointList lineFill = new PointList();
		lineFill.addPoint(PERSPECTIV_DEPTH, 0);
		lineFill.addPoint(rect.width - 1, 0);
		lineFill.addPoint(rect.width - 1, rect.height - PERSPECTIV_DEPTH - 1);
		lineFill.addPoint(rect.width - PERSPECTIV_DEPTH - 1, rect.height - 1);
		lineFill.addPoint(0, rect.height - 1);
		lineFill.addPoint(0, PERSPECTIV_DEPTH);
		graphics.fillPolygon(lineFill);
		
		// draw line 1
		PointList line1 = new PointList();
		line1.addPoint(PERSPECTIV_DEPTH, 0);
		line1.addPoint(rect.width - 1, 0);
		line1.addPoint(rect.width - 1, rect.height - PERSPECTIV_DEPTH - 1);
		line1.addPoint(rect.width - PERSPECTIV_DEPTH - 1, rect.height - 1);
		line1.addPoint(0, rect.height - 1);
		line1.addPoint(0, PERSPECTIV_DEPTH);
		graphics.drawPolygon(line1);  
		
		// draw line 2
		PointList line2 = new PointList();
		line2.addPoint(0, PERSPECTIV_DEPTH);
		line2.addPoint(rect.width-PERSPECTIV_DEPTH - 1, PERSPECTIV_DEPTH);
		line2.addPoint(rect.width - PERSPECTIV_DEPTH - 1, rect.height - 1);
		line2.addPoint(0, rect.height - 1);
		graphics.drawPolygon(line2);
		
		// draw line 3
		PointList line3 = new PointList();
		line3.addPoint(rect.width - PERSPECTIV_DEPTH - 1, PERSPECTIV_DEPTH);
		line3.addPoint(rect.width - 1, 0);
		graphics.drawPolygon(line3);

		graphics.translate(getLocation().getNegated());
	}
	
	/**
	 * 
	 * 
	 * @param graphics 
	 */
	public void paintBorder(Graphics graphics) {
		
	}

	/**
	 * Gets the name label.
	 * 
	 * @return the name label
	 */
	@Override
	public Label getNameLabel() {
		return labelFigure.getNameLabel();
	}

	/**
	 * Gets the qualified name label.
	 * 
	 * @return the qualified name label
	 */
	@Override
	public Label getQualifiedNameLabel() {
		return labelFigure.getQualifiedNameLabel();
	}

	/**
	 * Gets the stereotypes label.
	 * 
	 * @return the stereotypes label
	 */
	@Override
	public Label getStereotypesLabel() {
		return labelFigure.getStereotypesLabel();
	}

	/**
	 * Sets the bounds of the figure and its children.
	 * 
	 * @param rect the rect
	 */
	@Override
	public void setBounds(Rectangle rect) {
		Debug.debug(this, "setBounds(Rectangle)", channel);
		if (keywordFigure != null) {
			keywordFigure.setBounds(new Rectangle(rect));
		}
		labelFigure.setBounds(new Rectangle(rect));
		contentFigure.setBounds(new Rectangle(rect));
		super.setBounds(new Rectangle(rect));
	}

	/**
	 * Sets the name.
	 * 
	 * @param name the name
	 */
	@Override
	public void setName(String name) {
		labelFigure.setName(name);
	}

	/**
	 * Sets the qualified name.
	 * 
	 * @param qualifiedName the qualified name
	 */
	@Override
	public void setQualifiedName(String qualifiedName) {
		labelFigure.setQualifiedName(qualifiedName);
	}

	/**
	 * Sets the stereotypes.
	 * 
	 * @param stereotypes the stereotypes
	 */
	@Override
	public void setStereotypes(String stereotypes) {
		labelFigure.setStereotypes(stereotypes);
	}

	/**
	 * Refresh colors.
	 * 
	 * @param graphElement the graph element
	 */
	@Override
	public void refreshColors(GraphElement graphElement) {
		super.refreshColors(graphElement);
		labelFigure.setFontColor(getFontColor());
		labelFigure.setBorderColor(getBorderColor());
		labelFigure.setForeGroundColor(getForeGroundColor());
		
		Font baseFont = super.getNameLabel().getFont();
		if (baseFont.getFontData() != null){
			FontData baseFontData = baseFont.getFontData()[0];
			FontData[] labelFontData={new FontData(baseFontData.getName(), baseFontData.getHeight(), SWT.BOLD)};
			Font labelFont = PapyrusPlugin.fontManager.get(labelFontData);			
			labelFigure.setFont(labelFont);
		}
		if (keywordFigure != null) {
			keywordFigure.setFontColor(getFontColor());
			keywordFigure.setBorderColor(getBorderColor());
			keywordFigure.setForeGroundColor(getForeGroundColor());
			keywordFigure.setFont(PapyrusPlugin.fontManager.get(new FontData[]{new FontData(graphElement.getFontFamily(),graphElement.getFontSize(),SWT.NORMAL)}));
		}
		
		setForeGroundColor(getBorderColor());
	}

	/**
	 * Refresh presentation.
	 * 
	 * @param presentation the presentation
	 * @param selection the selection
	 */
	@Override
	public void refreshPresentation(String presentation, Element selection, GraphElement ge) {
		labelFigure.refreshPresentation(presentation, selection, ge);
	}

	/**
	 * 
	 * 
	 * @param isNameUnderlined 
	 */
	public void setNameUnderlined(boolean isNameUnderlined) {
		this.isNameUnderlined = isNameUnderlined;
	}

	/**
	 * Use local coordinates.
	 * 
	 * @return true, if use local coordinates
	 */
	@Override
	protected boolean useLocalCoordinates(){return true;}
}

